package slu.appli.wodtimer;

import slu.appli.logger.impl.SysoLogger;
import slu.appli.logger.interfaces.LoggerInterface;
import slu.appli.sound.interfaces.SoundPlayerInterface;
import slu.appli.tools.parser.stringparser.impl.treemodel.StringParserFactory;
import slu.appli.tools.parser.stringparser.interfaces.StringParserInterface;
import slu.appli.tools.parser.stringparser.interfaces.model.ModelReaderInterface;
import slu.appli.tools.parser.stringparser.interfaces.model.ModelReaderListenerInterface;
import slu.appli.wodtimer.info.WodTimerInformationControler;
import slu.appli.wodtimer.info.WodTimerInformationListenerInterface;
import slu.appli.wodtimer.listeners.BeepGeneratorListener;
import slu.appli.wodtimer.listeners.ElapseCounterListener;
import slu.appli.wodtimer.stringparser.EscapeChar2Hours;
import slu.appli.wodtimer.stringparser.EscapeChar2Minutes;
import slu.appli.wodtimer.stringparser.EscapeChar2Seconds;
import slu.appli.wodtimer.stringparser.EscapeCharCloseGroup;
import slu.appli.wodtimer.stringparser.EscapeCharOpenGroup;
import slu.appli.wodtimer.stringparser.EscapeCharSeparator;

public class WodTimer {
	private final StringParserInterface parser;
	private final WodTimerInformationControler infosControler;
	private LoggerInterface logger;


	public WodTimer() {
		super();
		this.logger = new SysoLogger();
		this.parser = StringParserFactory.newStringParser();
		this.parser.setAllowedCharList("0123456789");
		this.parser.setDataContext(new DataContext());
		this.parser.addEscapeChar(new EscapeCharSeparator());
		this.parser.addEscapeChar(new EscapeCharOpenGroup());
		this.parser.addEscapeChar(new EscapeCharCloseGroup());
		this.parser.addEscapeChar(new EscapeChar2Minutes());
		this.parser.addEscapeChar(new EscapeChar2Seconds());
		this.parser.addEscapeChar(new EscapeChar2Hours());
		this.infosControler = new WodTimerInformationControler();
	}
	
	public LoggerInterface getLogger() {
		return logger;
	}

	public void setLogger(LoggerInterface logger) {
		this.logger = logger;
	}
	
	private String normalizeString(String string) {
		String s = string.trim();
		if (!s.endsWith(";")) s = s + ";";
		return s;
	}

	public long computeDuration(String string) {
		ModelReaderInterface reader = this.parser.parseString(this.normalizeString(string));
		ElapseCounterListener counter = new ElapseCounterListener();
		reader.addModelReaderListener(counter);
		reader.read();
		return counter.getDuration();
	}
	
	public long processString(String string, SoundPlayerInterface player) {
		return this.processString(string, player, null);
	}
	
	public long processString(String string, SoundPlayerInterface player, ModelReaderListenerInterface listeners[]) {
		long duration = 0;
		try {
			ModelReaderInterface reader = parser.parseString(this.normalizeString(string));
			if (listeners != null) {
				for (ModelReaderListenerInterface listener : listeners) reader.addModelReaderListener(listener);
			}
	//		ElapseProcessingListener counter = new ElapseProcessingListener(this.logger);
			ElapseCounterListener counter = new ElapseCounterListener();
			reader.addModelReaderListener(new BeepGeneratorListener(player,this.logger,this.infosControler));
			reader.addModelReaderListener(counter);
			reader.read();
			duration = counter.getDuration();
		}
		catch (Exception e) {
			this.infosControler.markException();
			this.logger.addException(e);
		}
		return duration;
	}
	
	public void addListener(WodTimerInformationListenerInterface listener) {
		this.infosControler.addListener(listener);
	}
	
	public void removeListener(WodTimerInformationListenerInterface listener) {
		this.infosControler.removeListener(listener);
	}

}
